/**
 * Copyright 2013 yangming.liu<liuyangming@gmail.com>.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, see <http://www.gnu.org/licenses/>.
 */
package org.bytesoft.openjta.supports;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Set;

import org.bytesoft.openjta.archive.TerminatorArchive;
import org.bytesoft.openjta.archive.TransactionArchive;
import org.bytesoft.openjta.archive.XAResourceArchive;

public interface TransactionLogger {
	/* transaction */
	public void createTransaction(TransactionArchive transactionArchive);

	public void completePreparePhase(TransactionArchive transactionArchive);

	public void enterCommitPhase(TransactionArchive transactionArchive);

	public void enterRollbackPhase(TransactionArchive transactionArchive);

	public void completeCommitPhase(TransactionArchive transactionArchive);

	public void completeRollbackPhase(TransactionArchive transactionArchive);

	public void cleanupTransaction(TransactionArchive transactionArchive);

	/* xa resource */
	public void enterPrepareXAResource(XAResourceArchive archive);

	public void completePrepareXAResource(XAResourceArchive archive);

	public void enterCommitXAResource(XAResourceArchive archive);

	public void completeCommitXAResource(XAResourceArchive archive);

	public void enterRollbackXAResource(XAResourceArchive archive);

	public void completeRollbackXAResource(XAResourceArchive archive);

	/* terminator */
	public void enterPrepareTerminator(TerminatorArchive terminatorAchive);

	public void completePrepareTerminator(TerminatorArchive terminatorAchive);

	public void enterCommitTerminator(TerminatorArchive terminatorAchive);

	public void completeCommitTerminator(TerminatorArchive terminatorAchive);

	public void enterRollbackTerminator(TerminatorArchive terminatorAchive);

	public void completeRollbackTerminator(TerminatorArchive terminatorAchive);

	public void cleanupTerminator(TerminatorArchive terminatorAchive);

	/* recovery */
	public Set<TransactionArchive> getRecoveryArchives();

	/* default transaction logger */
	public static TransactionLogger defaultTransactionLogger = NullTransactionLoggerHanlder
			.getDefaultTransactionLogger();

	public static class NullTransactionLoggerHanlder implements InvocationHandler {
		private static final NullTransactionLoggerHanlder instance = new NullTransactionLoggerHanlder();

		private NullTransactionLoggerHanlder() {
		}

		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			System.out.printf("%4s[transaction-log] %s%n", "", method.getName());

			Class<?> clazz = method.getReturnType();
			if (Void.TYPE.equals(clazz)) {
				return null;
			} else if (Set.class.equals(clazz)) {
				return this.newInstance(HashSet.class);
			} else {
				return null;
			}
		}

		private Object newInstance(Class<?> clazz) {
			try {
				return clazz.newInstance();
			} catch (Exception ex) {
				return null;
			}
		}

		public static TransactionLogger getDefaultTransactionLogger() {
			return (TransactionLogger) Proxy.newProxyInstance(TransactionLogger.class.getClassLoader(),
					new Class[] { TransactionLogger.class }, instance);
		}
	}
}
